home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac-Source 1994 July
/
Mac-Source_July_1994.iso
/
Other Langs
/
MacPerl ƒ
/
Perl Source ƒ
/
MacPerl
/
MPUtils.c
< prev
next >
Wrap
Text File
|
1993-12-12
|
24KB
|
983 lines
/*********************************************************************
Project : MacPerl - Real Perl Application
File : MPEditUtils.c -
Author : Matthias Neeracher
A lot of this code is borrowed from 7Edit written by
Apple Developer Support UK
Started : 17Mar93 Language : MPW C
Modified : 29May93 MN Compiles correctly
30May93 MN Support Console Windows
14Aug93 MN Preference file
15Aug93 MN DoAbout
17Aug93 MN DoPrefDialog()
Last : 17Aug93
*********************************************************************/
#include <PLStringFuncs.h>
#include <Events.h>
#include <Traps.h>
#include <Dialogs.h>
#include <Fonts.h>
#include <Packages.h>
#include <ToolUtils.h>
#include <AppleEvents.h>
#include <TFileSpec.h>
#include <Folders.h>
#include <Resources.h>
#include <OSUtils.h>
#include <Files.h>
#include <Lists.h>
#include <Icons.h>
#include <string.h>
#include <GUSI.h>
#include <Desk.h>
#include <ctype.h>
#include <stdio.h>
#include "MPUtils.h"
#include "MPWindow.h"
#include <patchlevel.h>
/**-----------------------------------------------------------------------
Name: ShowError
Purpose: Reports an error to the user as both string and number.
-----------------------------------------------------------------------**/
#pragma segment Utils
pascal void ShowError(Str255 theError, long theErrorCode)
{
short alertResult;
Str255 theString;
if (gAppleEventsImplemented)
if (AEInteractWithUser(kAEDefaultTimeout, nil,nil))
return;
SetCursor(&qd.arrow);
NumToString(theErrorCode, theString);
ParamText(theError, theString, "", "");
alertResult = Alert(300, nil);
} /* ShowError */
/**-----------------------------------------------------------------------
Name: Ours
Purpose: Checks the frontmost window belongs to the app.
-----------------------------------------------------------------------**/
#pragma segment Utils
pascal Boolean Ours(WindowPtr aWindow)
{
if (aWindow)
if (((WindowPeek)aWindow)->windowKind == zoomDocProc)
return(true);
return(false);
} /* Ours */
/**-----------------------------------------------------------------------
Name: SetShortMenus
Purpose: Cuts the menus down to a minimum - Apple File Edit.
Greys out the unavailable options - used when no docs open
-----------------------------------------------------------------------**/
#pragma segment Utils
pascal void SetShortMenus()
{
DeleteMenu(windowID);
DisableItem(myMenus[fileM], fmClose);
DisableItem(myMenus[fileM], fmSave);
DisableItem(myMenus[fileM], fmSaveAs);
DisableItem(myMenus[fileM], fmRevert);
DisableItem(myMenus[fileM], fmPrint);
DisableItem(myMenus[fileM], fmPageSetUp);
/* now the unnecessary items on the edit menu */
DisableItem(myMenus[editM], undoCommand);
DisableItem(myMenus[editM], cutCommand);
DisableItem(myMenus[editM], copyCommand);
DisableItem(myMenus[editM], clearCommand);
DisableItem(myMenus[editM], pasteCommand);
DisableItem(myMenus[editM], selectAllCommand);
DrawMenuBar();
} /* SetShortMenus */
/**-----------------------------------------------------------------------
Name: SetLongMenus
Purpose: Reinstates the full menu bar - called when first document
opened.
-----------------------------------------------------------------------**/
#pragma segment Utils
pascal void SetLongMenus()
{
InsertMenu(myMenus[windowM], perlID);
EnableItem(myMenus[fileM], fmClose);
EnableItem(myMenus[fileM], fmSave);
EnableItem(myMenus[fileM], fmSaveAs);
EnableItem(myMenus[fileM], fmRevert);
EnableItem(myMenus[fileM], fmPrint);
EnableItem(myMenus[fileM], fmPageSetUp);
/* now the necessary items on the edit menu -
many other items fixed on each pass thru the main event
loop or before the window pulled down
*/
EnableItem(myMenus[editM], selectAllCommand);
DrawMenuBar();
} /* SetLongMenus */
/**-----------------------------------------------------------------------
Name: SetEditMenu
Purpose: Set the text of the edit menu according to the state of
current document.
-----------------------------------------------------------------------**/
#pragma segment Utils
pascal void SetEditMenu(DPtr theDoc)
{
#ifndef RUNTIME
if (theDoc->kind == kDocumentWindow && theDoc->u.reg.showBorders)
SetItem(myMenus[editM], cBorders, "\pHide Borders");
else
SetItem(myMenus[editM], cBorders, "\pShow Borders");
#endif
} /* SetEditMenu */
/**-----------------------------------------------------------------------
Name: GetTempFileName
Purpose: Fills newstring with a temporary file name.
-----------------------------------------------------------------------**/
#pragma segment Utils
pascal void GetTempFileName(DPtr aDoc, Str255 newString)
{
Str255 s;
Str255 fileName;
if (aDoc->kind != kDocumentWindow || aDoc->u.reg.everSaved == false)
PLstrcpy(fileName, "\pMacPerlTmp");
else
PLstrcpy(fileName, aDoc->theFileName);
/*generate a unique(ish) temporary filename*/
if (fileName[0] > 21)
fileName[0] = 21;
NumToString(TickCount(), s);
PLstrcat(fileName, s);
PLstrcpy(newString,fileName);
}
/**-----------------------------------------------------------------------
Name: SetText
Purpose: Sets the text of the supplied itemNo in aDialog to
theString and select it.
-----------------------------------------------------------------------**/
#pragma segment Utils
pascal void SetText(DialogPtr aDialog, short itemNo, Str255 theString)
{
Handle itemHandle;
Rect box;
short kind;
TEHandle theTEHandle;
GetDItem(aDialog, itemNo, &kind, &itemHandle, &box);
SetIText(itemHandle, theString);
theTEHandle = ((DialogPeek)aDialog)->textH;
/*set all the text to be selected*/
if (theTEHandle)
TESetSelect(0, 255, theTEHandle);
}
/**-----------------------------------------------------------------------
Name: RetrieveText
Purpose: Returns the text of anItem in aDialog in aString.
-----------------------------------------------------------------------**/
#pragma segment Utils
pascal void RetrieveText(DialogPtr aDialog, short anItem, Str255 aString)
{
short kind;
Rect box;
Handle itemHandle;
GetDItem(aDialog, anItem, &kind, &itemHandle, &box);
GetIText(itemHandle, aString);
}
/**-----------------------------------------------------------------------
Name: DrawDefaultOutline
Purpose: Draws an outline around theItem.
Called as a useritem Proc by the dialog manager.
To use place a useritem over the default item in the
dialog and install the address of this proc as the item
handle.
-----------------------------------------------------------------------**/
#pragma segment Utils
pascal void DrawDefaultOutline(DialogPtr theDialog, short theItem)
{
short kind;
Handle itemHandle;
Rect box;
GetDItem(theDialog, theItem, &kind, &itemHandle, &box);
PenSize(3, 3);
InsetRect(&box, -4, -4);
FrameRoundRect(&box, 16, 16);
PenNormal();
} /* DrawDefaultOutline */
/**-----------------------------------------------------------------------
Name: AdornDefaultButton
Purpose: Installs DrawDefaultOutline as the useritem proc
for the given item.
-----------------------------------------------------------------------**/
#pragma segment Utils
pascal void AdornDefaultButton(DialogPtr theDialog,short theItem)
{
short kind;
Handle itemHandle;
Rect box;
GetDItem(theDialog, theItem, &kind, &itemHandle, &box);
SetDItem(theDialog, theItem, kind, (Handle)&DrawDefaultOutline, &box);
}
pascal void GetRectOfDialogItem(DialogPtr theDialog, short theItem, Rect *theRect)
{
short kind;
Handle itemHandle;
GetDItem(theDialog, theItem, &kind, &itemHandle, theRect);
}
/**------ FeatureIsImplemented ------------**/
/* This is called to use Gestalt to determine if a feature is implemented.
This applies to only those referenced by OSType */
#pragma segment Utils
pascal Boolean FeatureIsImplemented(OSType theFeature, short theTestBit)
{
long result;
return !Gestalt(theFeature, &result) && (result & (1 << theTestBit));
}
#pragma segment Utils
pascal Boolean CheckEnvironment()
{
/*check for the AppleEvents manager - we certainly can't work without it*/
gAppleEventsImplemented = FeatureIsImplemented(gestaltAppleEventsAttr, gestaltAppleEventsPresent);
#ifndef RUNTIME
/*first check if the Edition Manager is present*/
gEditionManagerImplemented = FeatureIsImplemented(gestaltEditionMgrAttr, gestaltEditionMgrPresent);
/*and for good measure- the Alias manager*/
gAliasManagerImplemented = FeatureIsImplemented(gestaltAliasMgrAttr, gestaltAliasMgrPresent);
/*check if recording is implemented*/
gRecordingImplemented = FeatureIsImplemented(gestaltAppleEventsAttr,1);
/*check for the Outline fonts*/
gOutlineFontsImplemented = FeatureIsImplemented(gestaltFontMgrAttr, gestaltOutlineFonts);
return gEditionManagerImplemented &&
gAliasManagerImplemented &&
gAppleEventsImplemented &&
gOutlineFontsImplemented;
#else
return true;
#endif
} /* CheckEnvironment */
/*
DoPageSetup returns true if the page setup of the document is altered
*/
pascal Boolean DoPageSetup(DPtr theDoc)
{
if (theDoc) {
Boolean result;
PrOpen();
result = PrStlDialog(theDoc->thePrintSetup);
PrClose();
return(result);
}
} /* DoPageSetup */
/*
Name: CtrlKeyPressed
Purpose: Returns true if control key pressed during event
*/
pascal Boolean CtrlKeyPressed(const EventRecord *theEvent)
{
return theEvent->modifiers & controlKey;
}
/*
Name: OptionKeyPressed
Purpose: Returns true if option key pressed during event
*/
pascal Boolean OptionKeyPressed(const EventRecord *theEvent)
{
return theEvent->modifiers & optionKey;
}
pascal void DrawVersion(DialogPtr dlg, short item)
{
VersRecHndl vers;
short base;
Handle h;
Rect r;
FontInfo info;
Str15 patchlevel;
GetDItem(dlg, item, &base, &h, &r);
SetPort(dlg);
TextFont(1);
TextSize(10);
GetFontInfo(&info);
base = r.top+2+info.ascent;
MoveTo(r.left+2, base);
DrawString("\pVersion");
MoveTo((r.left+r.right) >> 1, r.top+2+info.ascent);
vers = (VersRecHndl) GetResource('vers', 1);
HLock((Handle) vers);
DrawString((*vers)->shortVersion);
ReleaseResource((Handle) vers);
base += info.ascent + info.descent + info.leading;
MoveTo(r.left+2, base);
DrawString("\pPatchlevel");
MoveTo((r.left+r.right) >> 1, base);
patchlevel[0] = sprintf((char *) patchlevel+1, "%d", PATCHLEVEL);
DrawString(patchlevel);
TextFont(CreditID);
TextSize(12);
}
pascal void DoAbout()
{
DialogPtr dlg;
short kind;
Handle hdl;
Rect bounds;
Rect hot;
Str255 string;
short * widths;
short count;
short current;
short offset;
EventRecord ev;
RgnHandle rgn;
long lastTicks;
SetCursor(&qd.arrow);
dlg = GetNewDialog(AboutDialog, nil, (WindowPtr) -1);
GetDItem(dlg, 2, &kind, &hdl, &bounds);
SetDItem(dlg, 2, kind, (Handle) DrawVersion, &bounds);
DrawDialog(dlg);
#ifndef RUNTIME
GetDItem(dlg, 1, &kind, &hdl, &bounds);
SetPort(dlg);
TextFont(CreditID);
TextSize(12);
TextFace(normal);
ClipRect(&bounds);
hot = bounds;
hot.left = hot.right-2;
kind = StringWidth("\p • ");
hdl = GetResource('STR#', CreditID);
count = **(short **) hdl;
widths = (short *) NewPtr(2 * count);
for (current = 0; current<count; ++current) {
GetIndString(string, CreditID, current+1);
widths[current] = StringWidth(string) + kind;
}
offset = 0;
current = 0;
rgn = NewRgn();
lastTicks= 0;
GetIndString(string, CreditID, current+1);
#endif
while (dlg) {
#ifndef RUNTIME
while (TickCount() < lastTicks + 2);
lastTicks = TickCount();
SetPort(dlg);
ScrollRect(&bounds, -2, 0, rgn);
ClipRect(&hot);
MoveTo(bounds.right - offset, bounds.bottom - 3);
DrawString(string);
DrawString("\p • ");
ClipRect(&bounds);
if ((offset += 2) >= widths[current]) {
current = (current+1) % count;
offset = 0;
GetIndString(string, CreditID, current+1);
}
#endif
if (WaitNextEvent(mDownMask+keyDownMask+activMask+updateMask+osMask, &ev, 1, nil))
switch (ev.what) {
case activateEvt:
if ((WindowPtr) ev.message != dlg)
DoActivate((WindowPtr)ev.message, (ev.modifiers & activeFlag) != 0);
break;
case updateEvt:
if ((WindowPtr) ev.message == dlg) {
BeginUpdate(dlg);
UpdtDialog(dlg, dlg->visRgn);
EndUpdate(dlg);
} else
DoUpdate(DPtrFromWindowPtr((WindowPtr)ev.message));
break;
case kOSEvent:
switch (ev.message & osEvtMessageMask) { /*high byte of message*/
case 0x01000000:
gInBackground = ((ev.message & resumeFlag) == 0);
}
if (!gInBackground)
break;
default:
DisposeDialog(dlg);
dlg = nil;
break;
}
}
}
static void CenterWindow(DialogPtr dlg)
{
Rect * screen;
short hPos;
short vPos;
screen = &qd.screenBits.bounds;
hPos = screen->right+screen->left-dlg->portRect.right >> 1;
vPos = (screen->bottom-screen->top-dlg->portRect.bottom)/3;
vPos += screen->top;
MoveWindow(dlg, hPos, vPos, true);
}
#ifdef RUNTIME
typedef long ICON[32];
typedef struct {
ICON icon;
ICON mask;
} ICN_;
typedef short icm[12];
typedef struct {
icm icon;
icm mask;
} icm_;
static void PlotICN_(ICN_ * icon, Rect * within, IconMode mode)
{
GrafPtr port;
BitMap bmap;
BitMap mask;
PenState ps;
Pattern ltGray;
long * lg;
GetPort(&port);
bmap.baseAddr = (Ptr) icon;
bmap.rowBytes = 4;
bmap.bounds.top = 0;
bmap.bounds.left = 0;
bmap.bounds.bottom= 32;
bmap.bounds.right = 32;
mask = bmap;
mask.baseAddr = (Ptr) icon->mask;
switch (mode) {
case iconGray:
GetPenState(&ps);
PenMode(patXor);
lg = (long *)<Gray;
lg[0] = 0x11004400;
lg[1] = lg[0];
PenPat(<Gray);
PaintRect(within);
CopyBits(&mask, &port->portBits, &mask.bounds, within, srcBic, nil);
PaintRect(within);
CopyBits(&bmap, &port->portBits, &bmap.bounds, within, srcOr, nil);
SetPenState(&ps);
break;
case iconHilited:
CopyBits(&mask, &port->portBits, &mask.bounds, within, srcOr, nil);
CopyBits(&bmap, &port->portBits, &bmap.bounds, within, srcXor, nil);
break;
default:
CopyBits(&mask, &port->portBits, &mask.bounds, within, srcBic, nil);
CopyBits(&bmap, &port->portBits, &bmap.bounds, within, srcXor, nil);
break;
}
}
pascal void PlotResICN_(short id, Rect * within, IconMode mode)
{
char flags;
ICN_ ** icon;
if (icon = (ICN_ **) GetResource('ICN#', id)) {
flags = HGetState((Handle) icon);
HLock((Handle) icon);
PlotICN_(*icon, within, mode);
HSetState((Handle) icon, flags);
}
}
static void PlotMiniIcon(icm_ * icon, Rect * within)
{
GrafPtr port;
BitMap bmap;
BitMap mask;
GetPort(&port);
bmap.baseAddr = (Ptr) icon;
bmap.rowBytes = 2;
bmap.bounds.top = 0;
bmap.bounds.left = 0;
bmap.bounds.bottom= 12;
bmap.bounds.right = 16;
mask = bmap;
mask.baseAddr = (Ptr) icon->mask;
CopyBits(&mask, &port->portBits, &mask.bounds, within, srcBic, nil);
CopyBits(&bmap, &port->portBits, &bmap.bounds, within, srcXor, nil);
}
pascal void PlotResMiniIcon(short id, Rect * within)
{
char flags;
icm_ ** icon;
if (icon = (icm_ **) GetResource('icm#', id)) {
flags = HGetState((Handle) icon);
HLock((Handle) icon);
PlotMiniIcon(*icon, within);
HSetState((Handle) icon, flags);
}
}
typedef struct {
Handle handle; /* handle or procedure pointer for this item */
Rect bounds; /* display rectangle for this item */
char type; /* item type - 1 */
char data[1]; /* length byte of data */
} DialogItem;
typedef struct {
short max_index; /* number of items - 1 */
DialogItem items[1]; /* first item in the array */
} **ItemListHandle;
pascal void Append_DITL(DialogPtr dialog, short item_list_ID)
{
ItemListHandle append_item_list; /* handle to DITL being appended */
DialogItem * item; /* pointer to item being appended */
ItemListHandle dlg_item_list; /* handle to DLOG's item list */
short i;
short sz;
dlg_item_list = (ItemListHandle) ((DialogPeek)dialog)->items;
append_item_list = (ItemListHandle)GetResource('DITL', item_list_ID);
if (!append_item_list)
return;
HLock((Handle)append_item_list);
item = (*append_item_list)->items;
for (i=0; i<=(*append_item_list)->max_index; ++i) {
switch (item->type & 0x7F) {
case ctrlItem + btnCtrl:
case ctrlItem + chkCtrl:
case ctrlItem + radCtrl:
item->handle =
(Handle)
NewControl(
(DialogPtr) dialog, &item->bounds,
(StringPtr)item->data,
true, 0, 0, 1,
item->type & 0x03,
0);
break;
case ctrlItem + resCtrl :
item->handle = (Handle)GetNewControl(*(int*)(item->data + 1), (DialogPtr) dialog);
(**(ControlHandle)item->handle).contrlRect = item->bounds;
break;
case statText :
case editText :
PtrToHand(item->data + 1, &item->handle, item->data[0]);
break;
case iconItem :
item->handle = GetIcon(*(int*)(item->data + 1));
break;
case picItem :
item->handle = (Handle)GetPicture(*(int*)(item->data + 1));
break;
default :
item->handle = NULL;
}
sz = (item->data[0] + 1) & 0xFFFE;
item = (DialogItem *)((char*)item + sz + sizeof(DialogItem));
}
PtrAndHand(
(*append_item_list)->items,
(Handle)dlg_item_list,
GetHandleSize((Handle) append_item_list) - 2);
(*dlg_item_list)->max_index += (*append_item_list)->max_index + 1;
HUnlock((Handle) append_item_list);
ReleaseResource((Handle) append_item_list);
}
pascal void Shorten_DITL(DialogPtr dialog, short shorten)
{
DialogItem * item; /* pointer to item being appended */
ItemListHandle dlg_item_list; /* handle to DLOG's item list */
short i;
short sz;
short restSize = -1;
dlg_item_list = (ItemListHandle) ((DialogPeek)dialog)->items;
HLock((Handle)dlg_item_list);
item = (*dlg_item_list)->items;
shorten = (*dlg_item_list)->max_index - shorten;
for (i=0; i<=(*dlg_item_list)->max_index; ++i) {
if (i > shorten)
switch (item->type & 0x7F) {
case ctrlItem + btnCtrl:
case ctrlItem + chkCtrl:
case ctrlItem + radCtrl:
case ctrlItem + resCtrl :
DisposeControl((ControlHandle) item->handle);
break;
case statText :
case editText :
DisposeHandle(item->handle);
break;
case iconItem :
case picItem :
ReleaseResource(item->handle);
break;
default :
break;
}
sz = (item->data[0] + 1) & 0xFFFE;
item = (DialogItem *)((char*)item + sz + sizeof(DialogItem));
if (i == shorten)
restSize = (char *) item - (char *) *dlg_item_list;
}
if (restSize >= 0) {
SetHandleSize((Handle) dlg_item_list, restSize);
(*dlg_item_list)->max_index = shorten;
}
HUnlock((Handle) dlg_item_list);
}
pascal short Count_DITL(DialogPtr dialog)
{
return (*(ItemListHandle) ((DialogPeek)dialog)->items)->max_index + 1;
}
#endif
pascal void Separator(DialogPtr dlg, short item)
{
short kind;
Handle h;
Rect r;
PenPat(&qd.gray);
GetDItem(dlg, item, &kind, &h, &r);
FrameRect(&r);
PenPat(&qd.black);
}
static DPtr Documents[50];
static short DocCount = 0;
pascal void RegisterDocument(DPtr doc)
{
Documents[DocCount++] = doc;
}
pascal void UnregisterDocument(DPtr doc)
{
short i,j;
for (i = 0, j = 0; i < DocCount; ++i)
if (Documents[i] != doc)
Documents[j++] = Documents[i];
DocCount = j;
}
pascal void SetupWindowMenu()
{
short i;
short item = 0;
WindowPtr front;
WindowPeek aWindow;
WindowPeek nextWindow;
MenuHandle menu;
Str255 name;
int needsSeparator = 0;
DisposeMenu(myMenus[windowM]);
menu = myMenus[windowM] = GetMenu(windowID);
front = FrontWindow();
for (i = 0; i < DocCount; ++i)
if (Documents[i]->kind != kDocumentWindow) {
AppendMenu(menu, "\px");
GetWTitle(Documents[i]->theWindow, name);
SetMenuItemText(menu, ++item, name);
if (!((WindowPeek) Documents[i]->theWindow)->visible)
SetItemStyle(menu, item, italic);
else if (Documents[i]->theWindow == front)
SetItemMark(menu, item, checkMark);
EnableItem(menu, item);
needsSeparator = 1;
}
for (i = 0; i < DocCount; ++i)
if (Documents[i]->kind == kDocumentWindow) {
if (needsSeparator && needsSeparator < 2) {
AppendMenu(menu, "\p-(");
++item;
}
AppendMenu(menu, "\px");
GetWTitle(Documents[i]->theWindow, name);
SetMenuItemText(menu, ++item, name);
if (!((WindowPeek) Documents[i]->theWindow)->visible)
SetItemStyle(menu, item, Documents[i]->dirty ? underline + italic : italic);
else {
if (Documents[i]->dirty)
SetItemStyle(menu, item, underline);
if (Documents[i]->theWindow == front)
SetItemMark(menu, item, checkMark);
}
EnableItem(menu, item);
needsSeparator = 2;
}
for (aWindow = (WindowPeek) FrontWindow(); aWindow; aWindow = nextWindow) {
nextWindow = aWindow->nextWindow;
if (aWindow->visible && !Ours((WindowPtr) aWindow)) {
if (needsSeparator && needsSeparator < 3) {
AppendMenu(menu, "\p-(");
++item;
}
AppendMenu(menu, "\px");
GetWTitle((WindowPtr) aWindow, name);
SetMenuItemText(menu, ++item, name);
if ((WindowPtr) aWindow == front)
SetItemMark(menu, item, checkMark);
EnableItem(menu, item);
needsSeparator = 3;
}
}
}
static void AnointWindow(WindowPtr win)
{
if (!((WindowPeek) win)->visible)
ShowWindow(win);
SelectWindow(win);
}
pascal void DoSelectWindow(short item)
{
short i;
WindowPeek aWindow;
WindowPeek nextWindow;
MenuHandle menu;
int needsSeparator = 0;
menu = myMenus[windowM];
for (i = 0; i < DocCount; ++i)
if (Documents[i]->kind != kDocumentWindow) {
if (!--item) {
AnointWindow(Documents[i]->theWindow);
return;
}
needsSeparator = 1;
}
for (i = 0; i < DocCount; ++i)
if (Documents[i]->kind == kDocumentWindow) {
if (needsSeparator && needsSeparator < 2) {
--item;
}
if (!--item) {
AnointWindow(Documents[i]->theWindow);
return;
}
needsSeparator = 2;
}
for (aWindow = (WindowPeek) FrontWindow(); aWindow; aWindow = nextWindow) {
nextWindow = aWindow->nextWindow;
if (aWindow->visible && !Ours((WindowPtr) aWindow)) {
if (needsSeparator && needsSeparator < 3) {
--item;
}
if (!--item) {
AnointWindow((WindowPtr) aWindow);
return;
}
needsSeparator = 3;
}
}
}
/* Borrowed from tech note 263 */
#define kKosherModifiers 0x0E00 // We keep only option & shift
#define kMaskVirtualKey 0x0000FF00 // get virtual key from event message
// for KeyTrans
#define kUpKeyMask 0x0080
#define kShiftWord 8 // we shift the virtual key to mask it
// into the keyCode for KeyTrans
#define kMaskASCII1 0x00FF0000 // get the key out of the ASCII1 byte
#define kMaskASCII2 0x000000FF // get the key out of the ASCII2 byte
pascal Boolean WeirdChar(const EventRecord * ev, short modifiers, char ch)
{
short keyCode;
long virtualKey, keyInfo, lowChar, highChar, state, keyCId;
Handle hKCHR;
Ptr KCHRPtr;
if ((ev->what == keyDown) || (ev->what == autoKey)) {
// see if the command key is down. If it is, find out the ASCII
// equivalent for the accompanying key.
if ((ev->modifiers & 0xFF00) == modifiers) {
virtualKey = (ev->message & kMaskVirtualKey) >> kShiftWord;
keyCode = (ev->modifiers & kKosherModifiers & ~modifiers) | virtualKey;
state = 0;
hKCHR = nil; /* set this to nil before starting */
KCHRPtr = (Ptr)GetEnvirons(smKCHRCache);
if ( !KCHRPtr ) {
keyCId = GetScript((short) GetEnvirons(smKeyScript), smScriptKeys);
hKCHR = GetResource('KCHR', (short) keyCId);
KCHRPtr = *hKCHR;
}
if (KCHRPtr) {
keyInfo = KeyTrans(KCHRPtr, keyCode, &state);
if (hKCHR)
ReleaseResource(hKCHR);
} else
keyInfo = ev->message;
lowChar = keyInfo & kMaskASCII2;
highChar = (keyInfo & kMaskASCII1) >> 16;
if (lowChar == ch || highChar == ch)
return true;
} // end the command key is down
} // end key down event
return false;
}